#ifndef __SHM_HPP__
#define __SHM_HPP__

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>

const std::string pathname = "/home/qian/lesson23/shm";
const int proj_id = 0x123;
const int g_size = 4096;
const int User = 1;
const int Creat = 2;

class Shm
{
public:
    Shm(const std::string& pathname, int proj_id, int id)
    :_pathname(pathname)
    ,_proj_id(proj_id)
    ,_id(id)
    {
        _key = GetKey();
        _shmid = GetShm();
        _shmaddr = attach();
    }
    //获取_shmaddr
    void* GetShmaddr()
    {
        return _shmaddr;
    }
    //生成一个key
    key_t GetKey()
    {
        key_t k = ftok(_pathname.c_str(), _proj_id);
        if(k < 0)
        {
            perror("ftok");
        }
        return k;
    }
    //创建共享内存和获取shmid
    int GetShm()
    {
        int shmid = shmget(_key, g_size, IPC_CREAT|0666);
        if(shmid == -1)
        {
            perror("shmget");
        }
        return shmid;
    }
    //挂接到共享内存上
    void* attach()
    {
        void* shmaddr = shmat(_shmid, nullptr, 0);
        if(shmaddr == nullptr)
        {
            perror("shmat");
        }
        return shmaddr;
    }
    //清空共享内存
    void zero()
    {
        if(_shmaddr != nullptr) memset((char*)_shmaddr, 0, g_size);
    }

    ~Shm()
    {
        //取消挂接
        if(_shmaddr!=nullptr) shmdt(_shmaddr);
        if(_id == Creat)
        {
            int ret = shmctl(_shmid, IPC_RMID, nullptr);
            if(ret == -1)
            {
                perror("shmctl");
            }
        }
    }
private:
    key_t _key; 
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _id;
    void* _shmaddr;
};

#endif